home *** CD-ROM | disk | FTP | other *** search
/ Collection of Internet / Collection of Internet.iso / msdos / lynx / source / www / library / implemen / htstyle.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-25  |  9.3 KB  |  376 lines

  1. /*    Style Implementation for Hypertext            HTStyle.c
  2. **    ==================================
  3. **
  4. **    Styles allow the translation between a logical property
  5. **    of a piece of text and its physical representation.
  6. **
  7. **    A StyleSheet is a collection of styles, defining the
  8. **    translation necessary to
  9. **    represent a document. It is a linked list of styles.
  10. */
  11. #include"capalloc.h"
  12. #include"capstdio.h"
  13. #include "HTStyle.h"
  14. #include "HTUtils.h"
  15.  
  16. /*    Create a new style
  17. */
  18. PUBLIC HTStyle* HTStyleNew NOARGS
  19. {
  20.     HTStyle * self = (HTStyle *)malloc(sizeof(*self));
  21.     memset(self, 0, sizeof(*self));
  22.     self->font = (HTFont) 0;
  23.     self->color = 0;
  24.     return self;
  25. }
  26.  
  27. /*    Create a new style with a name
  28. */
  29. PUBLIC HTStyle* HTStyleNewNamed ARGS1 (CONST char *,name)
  30. {
  31.     HTStyle * self = HTStyleNew();
  32.     StrAllocCopy(self->name, name);
  33.     return self;
  34. }
  35.  
  36.  
  37. /*    Free a style
  38. */
  39. PUBLIC HTStyle * HTStyleFree ARGS1 (HTStyle *,self)
  40. {
  41.     if (self->name) free(self->name);
  42.     if (self->SGMLTag) free(self->SGMLTag);
  43.     free(self);
  44.     return 0;
  45. }
  46.  
  47.  
  48. #ifdef SUPPRESS  /* Only on the NeXT */
  49. /*    Read a style from a stream    (without its name)
  50. **    --------------------------
  51. **
  52. **    Reads a style with paragraph information from a stream.
  53. **    The style name is not read or written by these routines.
  54. */
  55. #define NONE_STRING "(None)"
  56. #define HTStream NXStream
  57.  
  58. HTStyle * HTStyleRead (HTStyle * style, HTStream * stream)
  59. {
  60.     char myTag[STYLE_NAME_LENGTH];
  61.     char fontName[STYLE_NAME_LENGTH];
  62.     NXTextStyle *p;
  63.     int    tab;
  64.     int gotpara;        /* flag: have we got a paragraph definition? */
  65.     
  66.     NXScanf(stream, "%s%s%f%d",
  67.     myTag,
  68.     fontName,
  69.     &style->fontSize,
  70.     &gotpara);
  71.     if (gotpara) {
  72.     if (!style->paragraph) {
  73.         style->paragraph = malloc(sizeof(*(style->paragraph)));
  74.         style->paragraph->tabs = 0;
  75.     }
  76.     p = style->paragraph;
  77.     NXScanf(stream, "%f%f%f%f%hd%f%f%hd",
  78.         &p->indent1st,
  79.         &p->indent2nd,
  80.         &p->lineHt,
  81.         &p->descentLine,
  82.         &p->alignment,
  83.         &style->spaceBefore,
  84.         &style->spaceAfter,
  85.         &p->numTabs);
  86.     if (p->tabs) free(p->tabs);
  87.     p->tabs = malloc(p->numTabs * sizeof(p->tabs[0]));
  88.     for (tab=0; tab < p->numTabs; tab++) {
  89.         NXScanf(stream, "%hd%f",
  90.             &p->tabs[tab].kind,
  91.             &p->tabs[tab].x);
  92.     }
  93.     } else { /* No paragraph */
  94.         if (style->paragraph) {
  95.             free(style->paragraph);
  96.             style->paragraph = 0;
  97.     }
  98.     } /* if no paragraph */
  99.     StrAllocCopy(style->SGMLTag, myTag);
  100.     if (strcmp(fontName, NONE_STRING)==0)
  101.         style->font = 0;
  102.     else
  103.         style->font = [Font newFont:fontName size:style->fontSize];
  104.     return 0;
  105.  
  106. }
  107.  
  108.  
  109. /*    Write a style to a stream in a compatible way
  110. */
  111. HTStyle * HTStyleWrite (HTStyle * style, NXStream * stream)
  112. {
  113.     int tab;
  114.     NXTextStyle *p = style->paragraph;
  115.     NXPrintf(stream, "%s %s %f %d\n",
  116.     style->SGMLTag,
  117.     style->font ? [style->font name] : NONE_STRING,
  118.     style->fontSize,
  119.     p!=0);
  120.  
  121.     if (p) {
  122.     NXPrintf(stream, "\t%f %f %f %f %d %f %f\t%d\n",
  123.         p->indent1st,
  124.         p->indent2nd,
  125.         p->lineHt,
  126.         p->descentLine,
  127.         p->alignment,
  128.         style->spaceBefore,
  129.         style->spaceAfter,
  130.         p->numTabs);
  131.         
  132.     for (tab=0; tab < p->numTabs; tab++)
  133.         NXPrintf(stream, "\t%d %f\n",
  134.             p->tabs[tab].kind,
  135.             p->tabs[tab].x);
  136.     }
  137.     return style;
  138. }
  139.  
  140.  
  141. /*    Write a style to stdout for diagnostics
  142. */
  143. HTStyle * HTStyleDump (HTStyle * style)
  144. {
  145.     int tab;
  146.     NXTextStyle *p = style->paragraph;
  147.     printf("Style %d `%s' SGML:%s. Font %s %.1f point.\n",
  148.         style,
  149.     style->name,
  150.     style->SGMLTag,
  151.     [style->font name],
  152.     style->fontSize);
  153.     if (p) {
  154.         printf(
  155.         "\tIndents: first=%.0f others=%.0f, Height=%.1f Desc=%.1f\n"
  156.     "\tAlign=%d, %d tabs. (%.0f before, %.0f after)\n",
  157.         p->indent1st,
  158.         p->indent2nd,
  159.         p->lineHt,
  160.         p->descentLine,
  161.         p->alignment,
  162.         p->numTabs,
  163.         style->spaceBefore,
  164.         style->spaceAfter);
  165.         
  166.     for (tab=0; tab < p->numTabs; tab++) {
  167.         printf("\t\tTab kind=%d at %.0f\n",
  168.             p->tabs[tab].kind,
  169.             p->tabs[tab].x);
  170.         }
  171.     printf("\n");
  172.     } /* if paragraph */
  173.     return style;
  174. }
  175. #endif
  176.  
  177.  
  178. /*            StyleSheet Functions
  179. **            ====================
  180. */
  181.  
  182. /*    Searching for styles:
  183. */
  184. HTStyle * HTStyleNamed ARGS2 (HTStyleSheet *,self, CONST char *,name)
  185. {
  186.     HTStyle * scan;
  187.     for (scan=self->styles; scan; scan=scan->next)
  188.         if (0==strcmp(scan->name, name)) return scan;
  189. #ifndef RELEASE
  190.     if (TRACE) fprintf(stderr, "StyleSheet: No style named `%s'\n", name);
  191. #endif /* RELEASE */
  192.     return 0;
  193. }
  194.  
  195. #ifdef NEXT_SUPRESS        /* Not in general common code */
  196.  
  197. HTStyle * HTStyleMatching (HTStyleSheet * self, HTStyle *style)
  198. {
  199.     HTStyle * scan;
  200.     for (scan=self->styles; scan; scan=scan->next)
  201.         if (scan->paragraph == para) return scan;
  202.     return 0;
  203. }
  204.  
  205. /*    Find the style which best fits a given run
  206. **    ------------------------------------------
  207. **
  208. **    This heuristic is used for guessing the style for a run of
  209. **    text which has been pasted in. In order, we try:
  210. **
  211. **    A style whose paragraph structure is actually used by the run.
  212. **    A style matching in font
  213. **    A style matching in paragraph style exactly
  214. **    A style matching in paragraph to a degree
  215. */
  216.  
  217. HTStyle * HTStyleForRun (HTStyleSheet *self, NXRun *run)
  218. {
  219.     HTStyle * scan;
  220.     HTStyle * best = 0;
  221.     int    bestMatch = 0;
  222.     NXTextStyle * rp = run->paraStyle;
  223.     for (scan=self->styles; scan; scan=scan->next)
  224.         if (scan->paragraph == run->paraStyle) return scan;    /* Exact */
  225.  
  226.     for (scan=self->styles; scan; scan=scan->next){
  227.         NXTextStyle * sp = scan->paragraph;
  228.         if (sp) {
  229.         int match = 0;
  230.         if (sp->indent1st ==    rp->indent1st)    match = match+1;
  231.         if (sp->indent2nd ==    rp->indent2nd)    match = match+2;
  232.         if (sp->lineHt ==        rp->lineHt)    match = match+1;
  233.         if (sp->numTabs ==        rp->numTabs)    match = match+1;
  234.         if (sp->alignment ==    rp->alignment)    match = match+3;
  235.         if (scan->font ==        run->font)    match = match+10;
  236.         if (match>bestMatch) {
  237.             best=scan;
  238.             bestMatch=match;
  239.         }
  240.     }
  241.     }
  242. #ifndef RELEASE
  243.     if (TRACE) fprintf(stderr, "HTStyleForRun: Best match for style is %d out of 18\n",
  244.              bestMatch);
  245. #endif /* RELEASE */
  246.     return best;
  247. }
  248. #endif
  249.  
  250.  
  251. /*    Add a style to a sheet
  252. **    ----------------------
  253. */
  254. HTStyleSheet * HTStyleSheetAddStyle ARGS2
  255.   (HTStyleSheet *,self, HTStyle *,style)
  256. {
  257.     style->next = 0;        /* The style will go on the end */
  258.     if (!self->styles) {
  259.         self->styles = style;
  260.     } else {
  261.         HTStyle * scan;
  262.         for(scan=self->styles; scan->next; scan=scan->next); /* Find end */
  263.     scan->next=style;
  264.     }
  265.     return self;
  266. }
  267.  
  268.  
  269. /*    Remove the given object from a style sheet if it exists
  270. */
  271. HTStyleSheet * HTStyleSheetRemoveStyle ARGS2
  272.   (HTStyleSheet *,self, HTStyle *,style)
  273. {
  274.     if (self->styles = style) {
  275.         self->styles = style->next;
  276.     return self;
  277.     } else {
  278.         HTStyle * scan;
  279.     for(scan = self->styles; scan; scan = scan->next) {
  280.         if (scan->next = style) {
  281.             scan->next = style->next;
  282.         return self;
  283.         }
  284.     }
  285.     }
  286.     return 0;
  287. }
  288.  
  289. /*    Create new style sheet
  290. */
  291.  
  292. HTStyleSheet * HTStyleSheetNew NOARGS
  293. {
  294.     HTStyleSheet * self = (HTStyleSheet *)malloc(sizeof(*self));
  295.  
  296.     memset((void*)self, 0, sizeof(*self));    /* ANSI */
  297. /* Harbison c ref man says (char*)self
  298.    but k&r ansii and abc books and Think_C say (void*) */
  299.     
  300. /*    bzero(self, sizeof(*self)); */        /* BSD */
  301.     return self;
  302. }
  303.  
  304.  
  305. /*    Free off a style sheet pointer
  306. */
  307. HTStyleSheet * HTStyleSheetFree ARGS1 (HTStyleSheet *,self)
  308. {
  309.     HTStyle * style;
  310.     while((style=self->styles)!=0) {
  311.         self->styles = style->next;
  312.     HTStyleFree(style);
  313.     }
  314.     free(self);
  315.     return 0;
  316. }
  317.  
  318.  
  319. /*    Read a stylesheet from a typed stream
  320. **    -------------------------------------
  321. **
  322. **    Reads a style sheet from a stream.  If new styles have the same names
  323. **    as existing styles, they replace the old ones without changing the ids.
  324. */
  325.  
  326. #ifdef NEXT_SUPRESS  /* Only on the NeXT */
  327. HTStyleSheet * HTStyleSheetRead(HTStyleSheet * self, NXStream * stream)
  328. {
  329.     int numStyles;
  330.     int i;
  331.     HTStyle * style;
  332.     char styleName[80];
  333.     NXScanf(stream, " %d ", &numStyles);
  334. #ifndef RELEASE
  335.     if (TRACE) fprintf(stderr, "Stylesheet: Reading %d styles\n", numStyles);
  336. #endif /* RELEASE */
  337.     for (i=0; i<numStyles; i++) {
  338.         NXScanf(stream, "%s", styleName);
  339.         style = HTStyleNamed(self, styleName);
  340.     if (!style) {
  341.         style = HTStyleNewNamed(styleName);
  342.         (void) HTStyleSheetAddStyle(self, style);
  343.     }
  344.     (void) HTStyleRead(style, stream);
  345. #ifndef RELEASE
  346.     if (TRACE) HTStyleDump(style);
  347. #endif /* RELEASE */
  348.     }
  349.     return self;
  350. }
  351.  
  352. /*    Write a stylesheet to a typed stream
  353. **    ------------------------------------
  354. **
  355. **    Writes a style sheet to a stream.
  356. */
  357.  
  358. HTStyleSheet * HTStyleSheetWrite(HTStyleSheet * self, NXStream * stream)
  359. {
  360.     int numStyles = 0;
  361.     HTStyle * style;
  362.     
  363.     for(style=self->styles; style; style=style->next) numStyles++;
  364.     NXPrintf(stream, "%d\n", numStyles);
  365.     
  366. #ifndef RELEASE
  367.     if (TRACE) fprintf(stderr, "StyleSheet: Writing %d styles\n", numStyles);
  368. #endif /* RELEASE */
  369.     for (style=self->styles; style; style=style->next) {
  370.         NXPrintf(stream, "%s ", style->name);
  371.     (void) HTStyleWrite(style, stream);
  372.     }
  373.     return self;
  374. }
  375. #endif
  376.